home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Format 1995 June
/
MacFormat 25.iso
/
Shareware City
/
Developers
/
OutOfPhase1.1 Source
/
OutOfPhase Folder
/
AlgoWaveTableObject.c
< prev
next >
Wrap
Text File
|
1994-12-27
|
32KB
|
1,028 lines
/* AlgoWaveTableObject.c */
/*****************************************************************************/
/* */
/* Out Of Phase: Digital Music Synthesis on General Purpose Computers */
/* Copyright (C) 1994 Thomas R. Lawrence */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* */
/* Thomas R. Lawrence can be reached at tomlaw@world.std.com. */
/* */
/*****************************************************************************/
#include "MiscInfo.h"
#include "Audit.h"
#include "Debug.h"
#include "Definitions.h"
#include "AlgoWaveTableObject.h"
#include "AlgoWaveTableList.h"
#include "Memory.h"
#include "DataMunging.h"
#include "CodeCenter.h"
#include "PcodeStack.h"
#include "PcodeSystem.h"
#include "FixedPoint.h"
#include "MainWindowStuff.h"
#include "Alert.h"
#include "Numbers.h"
#include "AlgoWaveTableWindow.h"
#include "WaveTableStorage.h"
#include "CompilerRoot.h"
#include "FunctionCode.h"
#include "BufferedFileInput.h"
#include "BufferedFileOutput.h"
struct AlgoWaveTableObjectRec
{
MyBoolean DataModified;
char* Name;
char* AlgoWaveTableFormula;
MyBoolean NeedsToBeRebuilt;
WaveTableStorageRec* WaveTableData; /* NIL if not built */
NumBitsType NumBits;
long NumFrames;
long NumTables;
AlgoWaveTableWindowRec* AlgoWaveTableWindow;
struct CodeCenterRec* CodeCenter;
struct MainWindowRec* MainWindow;
AlgoWaveTableListRec* AlgoWaveTableList;
short SavedWindowXLoc;
short SavedWindowYLoc;
short SavedWindowWidth;
short SavedWindowHeight;
};
/* allocate and create a new algorithmic wave table */
AlgoWaveTableObjectRec* NewAlgoWaveTableObject(struct CodeCenterRec* CodeCenter,
struct MainWindowRec* MainWindow,
struct AlgoWaveTableListRec* AlgoWaveTableList)
{
AlgoWaveTableObjectRec* AlgoWaveTableObj;
AlgoWaveTableObj = (AlgoWaveTableObjectRec*)AllocPtrCanFail(
sizeof(AlgoWaveTableObjectRec),"AlgoWaveTableObjectRec");
if (AlgoWaveTableObj == NIL)
{
FailurePoint1:
return AlgoWaveTableObj;
}
AlgoWaveTableObj->Name = StringToBlockCopy("untitled");
if (AlgoWaveTableObj->Name == NIL)
{
FailurePoint2:
ReleasePtr((char*)AlgoWaveTableObj);
goto FailurePoint1;
}
AlgoWaveTableObj->AlgoWaveTableFormula = StringToBlockCopy(
"# frames : integer; tables : integer; data : fixedarray\x0a");
if (AlgoWaveTableObj->AlgoWaveTableFormula == NIL)
{
FailurePoint3:
ReleasePtr(AlgoWaveTableObj->Name);
goto FailurePoint2;
}
AlgoWaveTableObj->DataModified = False;
AlgoWaveTableObj->NeedsToBeRebuilt = True;
AlgoWaveTableObj->WaveTableData = NIL;
AlgoWaveTableObj->NumBits = eSample16bit;
AlgoWaveTableObj->NumFrames = 256;
AlgoWaveTableObj->NumTables = 256;
AlgoWaveTableObj->AlgoWaveTableWindow = NIL;
AlgoWaveTableObj->CodeCenter = CodeCenter;
AlgoWaveTableObj->MainWindow = MainWindow;
AlgoWaveTableObj->AlgoWaveTableList = AlgoWaveTableList;
AlgoWaveTableObj->SavedWindowXLoc = 0;
AlgoWaveTableObj->SavedWindowYLoc = 0;
AlgoWaveTableObj->SavedWindowWidth = 0;
AlgoWaveTableObj->SavedWindowHeight = 0;
return AlgoWaveTableObj;
}
/* dispose of all data structures associated with wave table */
void DisposeAlgoWaveTableObject(AlgoWaveTableObjectRec* AlgoWaveTableObj)
{
CheckPtrExistence(AlgoWaveTableObj);
if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
{
DisposeAlgoWaveTableWindow(AlgoWaveTableObj->AlgoWaveTableWindow);
ERROR(AlgoWaveTableObj->AlgoWaveTableWindow != NIL,PRERR(ForceAbort,
"DisposeAlgoWaveTableObject: window thing not NIL after disposing"));
}
ReleasePtr(AlgoWaveTableObj->Name);
ReleasePtr(AlgoWaveTableObj->AlgoWaveTableFormula);
if (AlgoWaveTableObj->WaveTableData != NIL)
{
DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
}
ReleasePtr((char*)AlgoWaveTableObj);
}
/* find out if any changes have been made to it */
MyBoolean HasAlgoWaveTableObjectBeenModified(AlgoWaveTableObjectRec* AlgoWaveTableObj)
{
CheckPtrExistence(AlgoWaveTableObj);
if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
{
return AlgoWaveTableObj->DataModified
|| HasAlgoWaveTableWindowBeenModified(AlgoWaveTableObj->AlgoWaveTableWindow);
}
else
{
return AlgoWaveTableObj->DataModified;
}
}
static FunctionParamRec ArgList[] =
{
{"frames",eInteger},
{"tables",eInteger},
{"data",eArrayOfFixed}
};
#define ARGLISTLENGTH (sizeof(ArgList) / sizeof(ArgList[0]))
/* rebuild the wave table and return True if successful */
MyBoolean AlgoWaveTableObjectBuild(AlgoWaveTableObjectRec* AlgoWaveTableObj)
{
char* Blob;
PcodeRec* FuncCode;
CompileErrors Error;
long LineNumber;
ParamStackRec* ParamList;
EvalErrors OtherError;
OpcodeRec* ErrorOpcode;
long OffendingInstruction;
DataTypes ReturnType;
char* Buffer;
largefixedsigned* Middle;
long Limit;
long Scan;
long NumberOfTablesInIt;
long TotalFrameCount;
CheckPtrExistence(AlgoWaveTableObj);
/* make sure we are unbuilt */
AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
ERROR(AlgoWaveTableObj->WaveTableData != NIL,PRERR(ForceAbort,
"AlgoWaveTableObjectBuild: unbuilt object but it still exists"));
/* bring the world up to date */
if (!MainWindowMakeUpToDateFunctions(AlgoWaveTableObj->MainWindow))
{
return False;
}
/* allocate the new wave table thing */
AlgoWaveTableObj->WaveTableData = NewWaveTableStorage(
AlgoWaveTableObjectGetNumBits(AlgoWaveTableObj),
AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj));
if (AlgoWaveTableObj->WaveTableData == NIL)
{
FailurePointNegative1:
AlertHalt("There is not enough memory available to compile the algorithmic "
"wave table generator function.",NIL);
}
for (Scan = 0; Scan < AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj); Scan += 1)
{
if (!WaveTableStorageAppendEntry(AlgoWaveTableObj->WaveTableData))
{
FailurePoint0:
DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
goto FailurePointNegative1;
}
}
/* prepare the text blob to be evaluated */
Blob = AlgoWaveTableObjectGetFormulaCopy(AlgoWaveTableObj);
if (Blob == NIL)
{
FailurePoint1:
goto FailurePoint0;
}
/* perform compilation */
Error = CompileSpecialFunction(ArgList,ARGLISTLENGTH,&LineNumber,
&ReturnType,Blob,&FuncCode);
ReleasePtr(Blob);
/* show the error message if there is one */
if (Error != eCompileNoError)
{
if (!AlgoWaveTableObjectOpenWindow(AlgoWaveTableObj))
{
AlertHalt("A compile error occurred but there is not enough "
"memory available to display the error message.",NIL);
return False;
}
AlgoWaveTableWindowHiliteLine(AlgoWaveTableObj->AlgoWaveTableWindow,LineNumber - 1);
AlertHalt("A compile error occurred: _",GetCompileErrorString(Error));
return False;
}
/* try to evaluate the code */
ParamList = NewParamStack();
if (ParamList == NIL)
{
SecondFailurePoint1:
DisposePcode(FuncCode);
AlertHalt("There is not enough memory available to evaluate the algorithmic "
"wave table generator function.",NIL);
return False;
}
/* add a space for the return value */
if (!AddIntegerToStack(ParamList,0))
{
SecondFailurePoint2:
DisposeParamStack(ParamList);
goto SecondFailurePoint1;
}
/* add the special parameters (SymbolStack order MUST be the same */
/* order as that used for the Parameterlist) */
if (!AddIntegerToStack(ParamList,AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj)))
{
goto SecondFailurePoint2;
}
if (!AddIntegerToStack(ParamList,AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)))
{
goto SecondFailurePoint2;
}
Buffer = AllocPtrCanFail(AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj)
* AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)
* sizeof(largefixedsigned),"degeneratesample");
if (Buffer == NIL)
{
goto SecondFailurePoint2;
}
Limit = PtrSize(Buffer);
for (Scan = 0; Scan < Limit; Scan += 1)
{
Buffer[Scan] = 0;
}
if (!AddArrayToStack(ParamList,Buffer))
{
ReleasePtr(Buffer);
goto SecondFailurePoint2;
}
/* executing the actual code */
OtherError = EvaluatePcode(ParamList,FuncCode,
AlgoWaveTableObj->CodeCenter,&ErrorOpcode,&OffendingInstruction,
AlgoWaveTableObj->MainWindow,
(SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleLeftCopy,
(SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleRightCopy,
(SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetSampleMonoCopy,
(SampleErrors (*)(void*,char*,long*))&MainWindowGetWaveTableFrameCount,
(SampleErrors (*)(void*,char*,long*))&MainWindowGetWaveTableTableCount,
(SampleErrors (*)(void*,char*,largefixedsigned**))&MainWindowGetWaveTableArray,
AlgoWaveTableObj->MainWindow,
(struct InteractionWindowRec* (*)(void*))&MainWindowGetInteractionWindow);
DisposePcode(FuncCode);
if (OtherError != eEvalNoError)
{
char* FuncNameString;
FuncCodeRec* ErrorFunction;
MyBoolean SuccessFlag;
/* present error message */
AlgoWaveTableObjectOpenWindow(AlgoWaveTableObj);
SuccessFlag = False;
ErrorFunction = GetFunctionFromOpcode(AlgoWaveTableObj->CodeCenter,ErrorOpcode);
if (ErrorFunction == NIL)
{
FuncNameString = StringToBlockCopy("<anonymous>");
}
else
{
FuncNameString = CopyPtr(GetFunctionName(ErrorFunction));
}
if (FuncNameString != NIL)
{
char* Key;
Key = StringToBlockCopy("_");
if (Key != NIL)
{
char* BaseMessage;
BaseMessage = StringFromRaw("Error in function _, instruction _: _");
if (BaseMessage != NIL)
{
char* FixedMessage1;
FixedMessage1 = ReplaceBlockCopy(BaseMessage,Key,FuncNameString);
if (FixedMessage1 != NIL)
{
char* NumberStr;
NumberStr = IntegerToString(OffendingInstruction);
if (NumberStr != NIL)
{
char* FixedMessage2;
FixedMessage2 = ReplaceBlockCopy(FixedMessage1,Key,NumberStr);
if (FixedMessage2 != NIL)
{
AlertHalt(FixedMessage2,GetPcodeErrorMessage(OtherError));
SuccessFlag = True;
ReleasePtr(FixedMessage2);
}
ReleasePtr(NumberStr);
}
ReleasePtr(FixedMessage1);
}
ReleasePtr(BaseMessage);
}
ReleasePtr(Key);
}
ReleasePtr(FuncNameString);
}
if (!SuccessFlag)
{
AlertHalt("There is not enough memory available to show the "
"compile error message.",NIL);
}
DisposeParamStack(ParamList);
return False;
}
/* add the new data */
Middle = (largefixedsigned*)GetStackArray(ParamList,3);
if (Middle == NIL)
{
AlertHalt("NIL array returned from algorithmic wave table function.",NIL);
RebuildFailurePoint1:
DisposeParamStack(ParamList);
DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
AlgoWaveTableObj->WaveTableData = NIL;
AlgoWaveTableObjectOpenWindow(AlgoWaveTableObj);
return False;
}
ERROR(PtrSize((char*)Middle) % sizeof(largefixedsigned) != 0,
PRERR(ForceAbort,"AlgoWaveTableObjectBuild: array alignment error"));
NumberOfTablesInIt = AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj);
TotalFrameCount = AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj);
if ((PtrSize((char*)Middle) / sizeof(largefixedsigned))
!= NumberOfTablesInIt * TotalFrameCount)
{
AlertHalt("Algorithmic wave table function returned array of wrong size.",NIL);
RebuildFailurePoint2:
goto RebuildFailurePoint1;
}
for (Scan = 0; Scan < NumberOfTablesInIt; Scan += 1)
{
long Index;
for (Index = 0; Index < TotalFrameCount; Index += 1)
{
WaveTableStorageSetFrame(AlgoWaveTableObj->WaveTableData,Scan,Index,
Middle[(Scan * TotalFrameCount) + Index]);
}
}
DisposeParamStack(ParamList);
AlgoWaveTableObj->NeedsToBeRebuilt = False;
return True;
}
/* remove the wave table data */
void AlgoWaveTableObjectUnbuild(AlgoWaveTableObjectRec* AlgoWaveTableObj)
{
CheckPtrExistence(AlgoWaveTableObj);
if (AlgoWaveTableObj->WaveTableData != NIL)
{
DisposeWaveTableStorage(AlgoWaveTableObj->WaveTableData);
AlgoWaveTableObj->WaveTableData = NIL;
}
}
/* rebuild the wave table if it hasn't been built and return success flag */
MyBoolean AlgoWaveTableObjectMakeUpToDate(AlgoWaveTableObjectRec* AlgoWaveTableObj)
{
CheckPtrExistence(AlgoWaveTableObj);
if ((AlgoWaveTableObj->WaveTableData == NIL) || (AlgoWaveTableObj->NeedsToBeRebuilt)
|| (AlgoWaveTableObj->AlgoWaveTableWindow != NIL))
{
return AlgoWaveTableObjectBuild(AlgoWaveTableObj);
}
else
{
return True;
}
}
/* get a copy of the name of this object */
char* AlgoWaveTableObjectGetNameCopy(AlgoWaveTableObjectRec* AlgoWaveTableObj)
{
char* NameTemp;
CheckPtrExistence(AlgoWaveTableObj);
if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
{
NameTemp = AlgoWaveTableWindowGetNameCopy(AlgoWaveTableObj->AlgoWaveTableWindow);
}
else
{
NameTemp = CopyPtr(AlgoWaveTableObj->Name);
}
if (NameTemp != NIL)
{
SetTag(NameTemp,"AlgoWaveTableNameCopy");
}
return NameTemp;
}
/* install a new name on the object. the object becomes owner of the name, so */
/* the caller should not dispose of it. */
void AlgoWaveTableObjectNewName(AlgoWaveTableObjectRec* AlgoWaveTableObj,
char* Name)
{
CheckPtrExistence(AlgoWaveTableObj);
CheckPtrExistence(Name);
ReleasePtr(AlgoWaveTableObj->Name);
SetTag(Name,"AlgoWaveTableName");
AlgoWaveTableObj->Name = Name;
AlgoWaveTableObj->DataModified = True;
AlgoWaveTableObj->NeedsToBeRebuilt = True;
AlgoWaveTableListAlgoWaveTableNameChanged(AlgoWaveTableObj->AlgoWaveTableList,
AlgoWaveTableObj);
}
/* get a copy of the formula that computes the algorithmic wave table */
char* AlgoWaveTableObjectGetFormulaCopy(AlgoWaveTableObjectRec* AlgoWaveTableObj)
{
char* TextCopy;
CheckPtrExistence(AlgoWaveTableObj);
if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
{
TextCopy = AlgoWaveTableWindowGetFormulaCopy(AlgoWaveTableObj->AlgoWaveTableWindow);
}
else
{
TextCopy = CopyPtr(AlgoWaveTableObj->AlgoWaveTableFormula);
}
if (TextCopy != NIL)
{
SetTag(TextCopy,"AlgoWaveTableFormulaCopy");
}
return TextCopy;
}
/* install a new formula for the algorithmic wave table. the object becomes the */
/* owner of the memory block so the caller should not dispose of it. */
void AlgoWaveTableObjectNewFormula(AlgoWaveTableObjectRec* AlgoWaveTableObj,
char* Formula)
{
CheckPtrExistence(AlgoWaveTableObj);
CheckPtrExistence(Formula);
ReleasePtr(AlgoWaveTableObj->AlgoWaveTableFormula);
SetTag(Formula,"AlgoWaveTableFormula");
AlgoWaveTableObj->AlgoWaveTableFormula = Formula;
AlgoWaveTableObj->DataModified = True;
AlgoWaveTableObj->NeedsToBeRebuilt = True;
}
/* find out how many bits are in each sample frame */
NumBitsType AlgoWaveTableObjectGetNumBits(AlgoWaveTableObjectRec* AlgoWaveTableObj)
{
CheckPtrExistence(AlgoWaveTableObj);
if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
{
return AlgoWaveTableWindowGetNumBits(AlgoWaveTableObj->AlgoWaveTableWindow);
}
else
{
return AlgoWaveTableObj->NumBits;
}
}
/* install a new number of bits in the object. */
void AlgoWaveTableObjectPutNumBits(AlgoWaveTableObjectRec* AlgoWaveTableObj,
NumBitsType NewNumBits)
{
CheckPtrExistence(AlgoWaveTableObj);
AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
ERROR((NewNumBits != eSample16bit) && (NewNumBits != eSample8bit),
PRERR(ForceAbort,"AlgoWaveTableObjectPutNumBits: bad value"));
AlgoWaveTableObj->NumBits = NewNumBits;
AlgoWaveTableObj->DataModified = True;
AlgoWaveTableObj->NeedsToBeRebuilt = True;
}
/* find out how many frames there are per table */
long AlgoWaveTableObjectGetNumTables(AlgoWaveTableObjectRec* AlgoWaveTableObj)
{
CheckPtrExistence(AlgoWaveTableObj);
if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
{
return AlgoWaveTableWindowGetNumTables(AlgoWaveTableObj->AlgoWaveTableWindow);
}
else
{
return AlgoWaveTableObj->NumTables;
}
}
/* set the number of tables in the wave table */
void AlgoWaveTableObjectPutNumTables(AlgoWaveTableObjectRec* AlgoWaveTableObj,
long NumTables)
{
CheckPtrExistence(AlgoWaveTableObj);
AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
if (NumTables < 0)
{
NumTables = 0;
}
AlgoWaveTableObj->NumTables = NumTables;
AlgoWaveTableObj->DataModified = True;
AlgoWaveTableObj->NeedsToBeRebuilt = True;
}
/* get number of frames in each table */
long AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObjectRec* AlgoWaveTableObj)
{
if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
{
return AlgoWaveTableWindowGetNumFrames(AlgoWaveTableObj->AlgoWaveTableWindow);
}
else
{
return AlgoWaveTableObj->NumFrames;
}
}
/* set the number of frames in each table */
void AlgoWaveTableObjectPutNumFrames(AlgoWaveTableObjectRec* AlgoWaveTableObj,
long NumFrames)
{
CheckPtrExistence(AlgoWaveTableObj);
AlgoWaveTableObjectUnbuild(AlgoWaveTableObj);
AlgoWaveTableObj->NumFrames = NumFrames;
AlgoWaveTableObj->DataModified = True;
AlgoWaveTableObj->NeedsToBeRebuilt = True;
}
/* get a raw slice of data from the wave table. if the wave table is modified, */
/* this pointer becomes invalid. */
char* AlgoWaveTableObjectGetRawSlice(AlgoWaveTableObjectRec* AlgoWaveTableObj,
long AlgoWaveTableIndex)
{
CheckPtrExistence(AlgoWaveTableObj);
ERROR((AlgoWaveTableIndex < 0) || (AlgoWaveTableIndex
> AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)),PRERR(ForceAbort,
"AlgoWaveTableObjectGetRawSlice: table index is out of range"));
return (char*)WaveTableStorageGetTable(AlgoWaveTableObj->WaveTableData,
AlgoWaveTableIndex);
}
/* make the wave table open it's editor window */
MyBoolean AlgoWaveTableObjectOpenWindow(AlgoWaveTableObjectRec* AlgoWaveTableObj)
{
CheckPtrExistence(AlgoWaveTableObj);
if (AlgoWaveTableObj->AlgoWaveTableWindow == NIL)
{
AlgoWaveTableObj->AlgoWaveTableWindow
= NewAlgoWaveTableWindow(AlgoWaveTableObj->MainWindow,
AlgoWaveTableObj,AlgoWaveTableObj->AlgoWaveTableList,
AlgoWaveTableObj->SavedWindowXLoc,AlgoWaveTableObj->SavedWindowYLoc,
AlgoWaveTableObj->SavedWindowWidth,AlgoWaveTableObj->SavedWindowHeight);
}
else
{
AlgoWaveTableWindowBringToTop(AlgoWaveTableObj->AlgoWaveTableWindow);
}
return (AlgoWaveTableObj->AlgoWaveTableWindow != NIL);
}
/* notify the object that the editor window is closing. the object should */
/* not take any action. */
void AlgoWaveTableObjectClosingWindowNotify(
AlgoWaveTableObjectRec* AlgoWaveTableObj,
short NewX, short NewY, short NewWidth, short NewHeight)
{
CheckPtrExistence(AlgoWaveTableObj);
ERROR(AlgoWaveTableObj->AlgoWaveTableWindow == NIL,PRERR(ForceAbort,
"AlgoWaveTableObjectClosingWindowNotify: window not open"));
AlgoWaveTableObj->AlgoWaveTableWindow = NIL;
AlgoWaveTableObj->SavedWindowXLoc = NewX;
AlgoWaveTableObj->SavedWindowYLoc = NewY;
AlgoWaveTableObj->SavedWindowWidth = NewWidth;
AlgoWaveTableObj->SavedWindowHeight = NewHeight;
}
/* the document's name has changed, so we need to update the window */
void AlgoWaveTableObjectGlobalNameChange(AlgoWaveTableObjectRec*
AlgoWaveTableObj, char* NewFilename)
{
CheckPtrExistence(AlgoWaveTableObj);
if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
{
AlgoWaveTableWindowGlobalNameChange(AlgoWaveTableObj->AlgoWaveTableWindow,
NewFilename);
}
}
/* Algorithmic Wave Table Object Subblock Format: */
/* 1-byte format version number */
/* should be 1 */
/* 2-byte little endian window X position (signed; origin at top-left corner) */
/* 2-byte little endian window Y position */
/* 2-byte little endian window width */
/* 2-byte little endian window height */
/* 4-byte little endian name length descriptor */
/* n-byte name string (line feed = 0x0a) */
/* 4-byte little endian formula length descriptor */
/* n-byte formula string (line feed = 0x0a) */
/* 4-byte little endian number of frames */
/* should be an integral power of 2 in the interval 2..65536 */
/* 4-byte little endian number of tables */
/* 1-byte number of bits */
/* should be either 8 or 16 */
/* read in an object from the file. */
FileLoadingErrors AlgoWaveTableObjectNewFromFile(AlgoWaveTableObjectRec** ObjectOut,
struct BufferedInputRec* Input, struct CodeCenterRec* CodeCenter,
struct MainWindowRec* MainWindow,
struct AlgoWaveTableListRec* AlgoWaveTableList)
{
AlgoWaveTableObjectRec* AlgoWaveTableObj;
unsigned char UnsignedChar;
signed long SignedLong;
signed short SignedShort;
FileLoadingErrors Error;
CheckPtrExistence(Input);
CheckPtrExistence(CodeCenter);
CheckPtrExistence(MainWindow);
CheckPtrExistence(AlgoWaveTableList);
AlgoWaveTableObj = (AlgoWaveTableObjectRec*)AllocPtrCanFail(
sizeof(AlgoWaveTableObjectRec),"AlgoWaveTableObjectRec");
if (AlgoWaveTableObj == NIL)
{
Error = eFileLoadOutOfMemory;
FailurePoint1:
return Error;
}
/* 1-byte format version number */
/* should be 1 */
if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
{
Error = eFileLoadDiskError;
FailurePoint2:
ReleasePtr((char*)AlgoWaveTableObj);
goto FailurePoint1;
}
if (UnsignedChar != 1)
{
Error = eFileLoadBadFormat;
FailurePoint3:
goto FailurePoint2;
}
/* 2-byte little endian window X position (signed; origin at top-left corner) */
if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
{
Error = eFileLoadDiskError;
FailurePoint4:
goto FailurePoint3;
}
AlgoWaveTableObj->SavedWindowXLoc = SignedShort;
/* 2-byte little endian window Y position */
if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
{
Error = eFileLoadDiskError;
FailurePoint5:
goto FailurePoint4;
}
AlgoWaveTableObj->SavedWindowYLoc = SignedShort;
/* 2-byte little endian window width */
if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
{
Error = eFileLoadDiskError;
FailurePoint6:
goto FailurePoint5;
}
AlgoWaveTableObj->SavedWindowWidth = SignedShort;
/* 2-byte little endian window height */
if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
{
Error = eFileLoadDiskError;
FailurePoint7:
goto FailurePoint6;
}
AlgoWaveTableObj->SavedWindowHeight = SignedShort;
/* 4-byte little endian name length descriptor */
if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
{
Error = eFileLoadDiskError;
FailurePoint8:
goto FailurePoint7;
}
if (SignedLong < 0)
{
Error = eFileLoadBadFormat;
FailurePoint9:
goto FailurePoint8;
}
/* n-byte name string (line feed = 0x0a) */
AlgoWaveTableObj->Name = AllocPtrCanFail(SignedLong,"AlgoWaveTableObjectRec: name");
if (AlgoWaveTableObj->Name == NIL)
{
Error = eFileLoadOutOfMemory;
FailurePoint10:
goto FailurePoint9;
}
if (!ReadBufferedInput(Input,SignedLong,AlgoWaveTableObj->Name))
{
Error = eFileLoadDiskError;
FailurePoint11:
ReleasePtr(AlgoWaveTableObj->Name);
goto FailurePoint10;
}
/* 4-byte little endian formula length descriptor */
if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
{
Error = eFileLoadDiskError;
FailurePoint12:
goto FailurePoint11;
}
if (SignedLong < 0)
{
Error = eFileLoadBadFormat;
FailurePoint13:
goto FailurePoint12;
}
/* n-byte formula string (line feed = 0x0a) */
AlgoWaveTableObj->AlgoWaveTableFormula = AllocPtrCanFail(SignedLong,
"AlgoWaveTableObjectRec: formula");
if (AlgoWaveTableObj->AlgoWaveTableFormula == NIL)
{
Error = eFileLoadOutOfMemory;
FailurePoint14:
goto FailurePoint13;
}
if (!ReadBufferedInput(Input,SignedLong,AlgoWaveTableObj->AlgoWaveTableFormula))
{
Error = eFileLoadDiskError;
FailurePoint15:
ReleasePtr(AlgoWaveTableObj->AlgoWaveTableFormula);
goto FailurePoint14;
}
/* 4-byte little endian number of frames */
/* should be an integral power of 2 between 2 and 65536 */
if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
{
Error = eFileLoadDiskError;
FailurePoint16:
goto FailurePoint15;
}
if ((SignedLong != 2) && (SignedLong != 4) && (SignedLong != 8)
&& (SignedLong != 16) && (SignedLong != 32) && (SignedLong != 64)
&& (SignedLong != 128) && (SignedLong != 256) && (SignedLong != 512)
&& (SignedLong != 1024) && (SignedLong != 2048) && (SignedLong != 4096)
&& (SignedLong != 8192) && (SignedLong != 16384) && (SignedLong != 32768)
&& (SignedLong != 65536))
{
Error = eFileLoadBadFormat;
FailurePoint17:
goto FailurePoint16;
}
AlgoWaveTableObj->NumFrames = SignedLong;
/* 4-byte little endian number of tables */
if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
{
Error = eFileLoadDiskError;
FailurePoint18:
goto FailurePoint17;
}
if (SignedLong < 0)
{
Error = eFileLoadBadFormat;
FailurePoint19:
goto FailurePoint18;
}
AlgoWaveTableObj->NumTables = SignedLong;
/* 1-byte number of bits */
/* should be either 8 or 16 */
if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
{
Error = eFileLoadDiskError;
FailurePoint20:
goto FailurePoint19;
}
if (UnsignedChar == 8)
{
AlgoWaveTableObj->NumBits = eSample8bit;
}
else if (UnsignedChar == 16)
{
AlgoWaveTableObj->NumBits = eSample16bit;
}
else
{
Error = eFileLoadBadFormat;
FailurePoint21:
goto FailurePoint20;
}
/* fill in the other fields */
AlgoWaveTableObj->DataModified = False;
AlgoWaveTableObj->NeedsToBeRebuilt = True;
AlgoWaveTableObj->WaveTableData = NIL;
AlgoWaveTableObj->AlgoWaveTableWindow = NIL;
AlgoWaveTableObj->CodeCenter = CodeCenter;
AlgoWaveTableObj->MainWindow = MainWindow;
AlgoWaveTableObj->AlgoWaveTableList = AlgoWaveTableList;
*ObjectOut = AlgoWaveTableObj;
return eFileLoadNoError;
}
/* write the object out to the file. */
FileLoadingErrors AlgoWaveTableObjectWriteDataOut(
AlgoWaveTableObjectRec* AlgoWaveTableObj,
struct BufferedOutputRec* Output)
{
char* StringTemp;
CheckPtrExistence(AlgoWaveTableObj);
CheckPtrExistence(Output);
/* 1-byte format version number */
/* should be 1 */
if (!WriteBufferedUnsignedChar(Output,1))
{
return eFileLoadDiskError;
}
/* 2-byte little endian window X position (signed; origin at top-left corner) */
/* note that if the window is open when the file is saved, then the most recent */
/* coordinates of the window will not be used. */
if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowXLoc))
{
return eFileLoadDiskError;
}
/* 2-byte little endian window Y position */
if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowYLoc))
{
return eFileLoadDiskError;
}
/* 2-byte little endian window width */
if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowWidth))
{
return eFileLoadDiskError;
}
/* 2-byte little endian window height */
if (!WriteBufferedSignedShortLittleEndian(Output,AlgoWaveTableObj->SavedWindowHeight))
{
return eFileLoadDiskError;
}
/* 4-byte little endian name length descriptor */
StringTemp = AlgoWaveTableObjectGetNameCopy(AlgoWaveTableObj);
if (StringTemp == NIL)
{
return eFileLoadOutOfMemory;
}
if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
{
ReleasePtr(StringTemp);
return eFileLoadDiskError;
}
/* n-byte name string (line feed = 0x0a) */
if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
{
ReleasePtr(StringTemp);
return eFileLoadDiskError;
}
ReleasePtr(StringTemp);
/* 4-byte little endian formula length descriptor */
StringTemp = AlgoWaveTableObjectGetFormulaCopy(AlgoWaveTableObj);
if (StringTemp == NIL)
{
return eFileLoadOutOfMemory;
}
if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
{
ReleasePtr(StringTemp);
return eFileLoadDiskError;
}
/* n-byte formula string (line feed = 0x0a) */
if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
{
ReleasePtr(StringTemp);
return eFileLoadDiskError;
}
ReleasePtr(StringTemp);
/* 4-byte little endian number of frames */
/* should be an integral power of 2 between 2 and 65536 */
if (!WriteBufferedSignedLongLittleEndian(Output,
AlgoWaveTableObjectGetNumFrames(AlgoWaveTableObj)))
{
return eFileLoadDiskError;
}
/* 4-byte little endian number of tables */
if (!WriteBufferedSignedLongLittleEndian(Output,
AlgoWaveTableObjectGetNumTables(AlgoWaveTableObj)))
{
return eFileLoadDiskError;
}
/* 1-byte number of bits */
/* should be either 8 or 16 */
switch (AlgoWaveTableObjectGetNumBits(AlgoWaveTableObj))
{
default:
EXECUTE(PRERR(ForceAbort,"AlgoWaveTableObjectWriteDataOut: bad num bits"));
break;
case eSample8bit:
if (!WriteBufferedUnsignedChar(Output,8))
{
return eFileLoadDiskError;
}
break;
case eSample16bit:
if (!WriteBufferedUnsignedChar(Output,16))
{
return eFileLoadDiskError;
}
break;
}
return eFileLoadNoError;
}
/* mark algorithmic wave table object as saved */
void AlgoWaveTableObjectMarkAsSaved(AlgoWaveTableObjectRec* AlgoWaveTableObj)
{
CheckPtrExistence(AlgoWaveTableObj);
if (AlgoWaveTableObj->AlgoWaveTableWindow != NIL)
{
AlgoWaveTableWindowWritebackModifiedData(AlgoWaveTableObj->AlgoWaveTableWindow);
}
AlgoWaveTableObj->DataModified = False;
}